package com.example.langchain4j.controller;

import com.example.langchain4j.common.Result;
import com.example.langchain4j.service.DifyChangeService;
import com.example.langchain4j.utils.DocumentUtils;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * Workflow 前端对接接口
 * 用于替代原来的 Dify workflow,使用 LangChain 实现
 */
@RestController
@RequestMapping("/api/files")
@Tag(name = "Workflow前端对接接口")
@Slf4j
public class WorkflowController {

    @Resource
    private DifyChangeService difyChangeService;

    @Resource
    @Qualifier("chatLanguageModel")
    private ChatLanguageModel chatLanguageModel;

    @Resource
    private com.example.langchain4j.service.InterrogationGenerationService interrogationGenerationService;

    // 存储生成的文件路径
    private static final String GENERATED_DIR = "backend/src/main/resources/generated";

    /**
     * 上传文件并生成审批表
     * 对接 workflow 前端的 /api/files/upload 接口
     */
    @Operation(summary = "上传文件并生成审批表")
    @PostMapping("/upload")
    public Result<Map<String, Object>> uploadFiles(
            @RequestParam("files") MultipartFile[] files,
            @RequestParam(value = "sessionId", required = false) String sessionId) {

        log.info("收到文件上传请求, sessionId: {}, 文件数量: {}", sessionId, files.length);

        if (files.length != 2) {
            return Result.error("请上传两个文件: 监督检查记录和责令整改通知书");
        }

        try {
            MultipartFile file1 = files[0];
            MultipartFile file2 = files[1];

            log.info("文件1: {}, 大小: {}", file1.getOriginalFilename(), file1.getSize());
            log.info("文件2: {}, 大小: {}", file2.getOriginalFilename(), file2.getSize());

            // 提取文档内容
            String document1Content = DocumentUtils.extractTextFromWord(file1);
            String document2Content = DocumentUtils.extractTextFromWord(file2);

            log.info("文档内容提取完成");

            // 生成审批表文件
            Map<String, String> generationResult = generateShenpibiaoFile(document1Content, document2Content);
            String generatedFileName = generationResult.get("fileName");
            String jsonData = generationResult.get("jsonData");

            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("message", "文件上传并处理成功");
            result.put("generatedFile", generatedFileName);
            result.put("outputPath", GENERATED_DIR + "/" + generatedFileName);
            result.put("filePath", "http://localhost:8018/api/generated/" + generatedFileName);
            result.put("jsonData", jsonData); // 添加JSON数据用于后续生成笔录

            log.info("处理完成, 生成文件: {}", generatedFileName);

            return Result.success(result);

        } catch (Exception e) {
            log.error("处理文件失败", e);
            return Result.error("处理文件失败: " + e.getMessage());
        }
    }

    /**
     * 生成审批表文件
     * 返回包含fileName和jsonData的Map
     */
    private Map<String, String> generateShenpibiaoFile(String document1Content, String document2Content) throws Exception {
        // 确保generated目录存在
        Path generatedPath = Paths.get(GENERATED_DIR);
        if (!Files.exists(generatedPath)) {
            Files.createDirectories(generatedPath);
        }

        // 生成文件名
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");
        String timestamp = LocalDateTime.now().format(formatter);
        String fileName = "行政处罚立案审批表_" + timestamp + ".docx";
        String filePath = GENERATED_DIR + "/" + fileName;

        // 使用与 DifyChangeService 相同的逻辑生成文档
        log.info("开始生成审批表文档...");

        // 第一步: 生成简要案情
        String generalJianYaoAnQing = """
                {{document1Content}}{{document2Content}}
                根据用户输入的两个文件，生成案情描述，格式必须严格按照示例，不得自行改变结构或增加额外小标题。
                在生成“位于XXX”这一句时：
                使用消防监督检查记录表中“被查建筑物名称”要用完整的名称包括括号中的内容，联网查询到对应的实际物理地址，必须联网查询！！比如被查建筑物是宜宾市第一人民医院（西区总院），就必须使用这个完整的名称，包括"（西区总院）"联网查询到具体地址；
                严禁使用“被查单位地址”；
                
                如果建筑物名称与单位不同，则必须以建筑物为准，联网查询其实际地址并写入“位于XXX”。
                违法行为必须写进案情文段中，和示例保持一致，不能额外输出“违法行为匹配结果”部分。
                示例模式：先写发现的隐患问题，后写复查情况，再写“涉嫌违反了《中华人民共和国消防法》……之规定”。
                每一条违法行为都必须在文段里和法律条款逐一对应，不能省略。
                人员姓名、时间、通知书编号等，必须严格根据文件实际内容生成，不得编造。
                法律条款必须来自《消防行政处罚裁量权基准（2025.09）》中的“法律规定”列，不得出现“裁量权基准”字样。
                输出文段时不得使用任何 markdown 语法。
                示例格式（必须模仿）：
                简要案情: 2025 年04 月25 日，宜宾市消防救援支队防火监督人员谢远、姜兴涛对位于宜宾市文星街65号的宜宾市第一人民医院（西区总院）开展“双随机、一公开”消防监督抽查时发现：CRT 图形显示装置故障；地下室气体灭火系统的钢瓶间无法使用；23 层室内消火栓无水；23 层疏散走道设置杂物柜；综合楼全部避难间设置为病房等问题隐患，并向该单位下发了《责令限期改正通知书》（宜消限字【2025】第0XXX号）。2025 年06 月10 日，宜宾市消防救援支队防火监督人员谢远、李杜（因姜兴涛公差在外进行调整）对上述火灾隐患整改情况进行复查，发现该单位地下室气体灭火系统的钢瓶间无法使用和综合楼全部避难间设置为病房的火灾隐患未整改，涉嫌违反了《中华人民共和国消防法》第十六条第一款第（五）项之规定，建议立案查处。""\";
                """;

        PromptTemplate promptTemplate1 = PromptTemplate.from(generalJianYaoAnQing);
        HashMap<String, Object> vary1 = new HashMap<>();
        vary1.put("document1Content", document1Content);
        vary1.put("document2Content", document2Content);
        Prompt prompt1 = promptTemplate1.apply(vary1);

        ChatResponse chatResponse1 = chatLanguageModel.chat(prompt1.toUserMessage());
        String jianyaoanqingRes = chatResponse1.aiMessage().text();
        log.info("简要案情生成完成: {}", jianyaoanqingRes);

        // 第二步: 生成审批表JSON
        String generalShenpibiaoJson = """
            {{document1Content}}{{document2Content}}
            根据上面两个用户上传的文件提取相关信息，并填写下面的模板。
            请严格按照以下 JSON 模板填充，所有字段必须保留，不得新增或删除。
            如果文档中没有对应内容，请填空字符串 ""。
            其中简要案情直接填写{{jianyaoanqingRes}}的内容，不要对简要案情进行任何修改，不要修改，不要修改。
            勾选项必须用 "☑" 或 "☐" 表示，不可用 true/false。
            案情等长文本内容必须完整保留。
            {
              "org_name": "",            // 消防救援机构名称，例如：宜宾市消防救援支队
              "year": "",                // 案号年份，例如：2025
              "case_no": "",             // 案号序号，例如：0002
              "case_source_1": "",       // 案件来源：1.消防监督管理工作中发现（☑/☐）
              "case_source_2": "",       // 案件来源：2.举报（☑/☐）
              "case_source_3": "",       // 案件来源：3.移送（☑/☐）
              "case_source_4": "",       // 案件来源：4.其他（☑/☐）
              "case_reason": "",         // 案由，例如：不及时消除火灾隐患；    
              "person_name": "",         // 当事人姓名（个人）
              "person_gender": "",       // 当事人性别
              "person_birth": "",        // 出生日期，格式：YYYY年MM月DD日
              "person_id_type": "",      // 身份证件种类
              "person_id_no": "",        // 身份证件号码
              "person_address": "",      // 住址
              "person_contact": "",      // 联系方式
              "unit_name": "",           // 单位名称
              "unit_legal_person": "",   // 法定代表人
              "unit_address": "",        // 单位地址
              "unit_contact": "",        // 单位联系方式
              "unit_credit_code": "",    // 单位统一社会信用代码
              "case_brief": "",          // 简要案情，直接填写{{jianyaoanqingRes}}的内容，不要进行任何修改，不要修改，不要修改
              "opinion_1": "",           // 立案意见：属本单位管辖（☑/☐）
              "opinion_2": "",           // 立案意见：移送（☑/☐）
              "opinion_3": "",           // 立案意见：不予调查（☑/☐）
              "opinion_4": "",           // 立案意见：其他（☑/☐）
              "law_enforcers": "",       // 执法人员姓名，多个用顿号隔开
              "law_date": "",            // 执法日期，格式：YYYY年MM月DD日 
              "main_handler": "",        // 主责承办人
              "assistant_handler": "",   // 协办人
              "leader_name": "",         // 消防救援机构负责人
              "leader_date": ""          // 审批日期，格式：YYYY年MM月DD日
            }
            """;

        vary1.put("jianyaoanqingRes", jianyaoanqingRes);
        PromptTemplate promptTemplate2 = PromptTemplate.from(generalShenpibiaoJson);
        Prompt prompt2 = promptTemplate2.apply(vary1);
        ChatResponse chatResponse2 = chatLanguageModel.chat(prompt2.toUserMessage());
        String shenpibiaoJsonRes = chatResponse2.aiMessage().text();

        // 清理JSON字符串，移除可能的markdown标记和推理过程
        shenpibiaoJsonRes = cleanJsonString(shenpibiaoJsonRes);

        log.info("审批表JSON生成完成: {}", shenpibiaoJsonRes);

        // 第三步: 填充Word模板并保存到指定路径
        cn.hutool.json.JSONObject resultMap = cn.hutool.json.JSONUtil.parseObj(shenpibiaoJsonRes);

        // 从resources目录加载审批表模板
        org.springframework.core.io.ClassPathResource resource =
            new org.springframework.core.io.ClassPathResource("行政处罚立案审批表template.docx");

        try (java.io.InputStream templateInputStream = resource.getInputStream()) {
            com.deepoove.poi.XWPFTemplate template =
                com.deepoove.poi.XWPFTemplate.compile(templateInputStream).render(resultMap);

            // 保存到指定路径
            java.io.FileOutputStream out = new java.io.FileOutputStream(filePath);
            template.write(out);
            out.close();
            template.close();
        }

        log.info("审批表文件生成完成: {}", filePath);

        // 返回文件名和JSON数据
        Map<String, String> result = new HashMap<>();
        result.put("fileName", fileName);
        result.put("jsonData", shenpibiaoJsonRes);
        return result;
    }

    /**
     * 清理JSON字符串，移除markdown代码块标记和额外说明
     * 特别处理推理模型（如qwq）的思考过程输出
     */
    private String cleanJsonString(String jsonString) {
        if (jsonString == null || jsonString.trim().isEmpty()) {
            return jsonString;
        }

        String cleaned = jsonString.trim();

        // 移除开头的markdown标记
        if (cleaned.startsWith("```json")) {
            cleaned = cleaned.substring(7);
        } else if (cleaned.startsWith("```")) {
            cleaned = cleaned.substring(3);
        }

        // 移除结尾的markdown标记
        if (cleaned.endsWith("```")) {
            cleaned = cleaned.substring(0, cleaned.length() - 3);
        }

        cleaned = cleaned.trim();

        // 特殊处理：如果内容包含思考过程（常见于推理模型），尝试提取JSON部分
        // 查找最后一个完整的JSON对象（从最后一个 } 往前找到对应的 {）
        int lastBrace = cleaned.lastIndexOf('}');
        if (lastBrace != -1) {
            // 从lastBrace往前找匹配的 {
            int braceCount = 1;
            int firstBrace = lastBrace - 1;
            while (firstBrace >= 0 && braceCount > 0) {
                if (cleaned.charAt(firstBrace) == '}') {
                    braceCount++;
                } else if (cleaned.charAt(firstBrace) == '{') {
                    braceCount--;
                }
                firstBrace--;
            }
            firstBrace++; // 调整到 { 的位置

            if (firstBrace >= 0 && braceCount == 0) {
                // 找到了完整的JSON对象
                String potentialJson = cleaned.substring(firstBrace, lastBrace + 1);
                // 验证是否像JSON（简单检查：包含引号和冒号）
                if (potentialJson.contains("\"") && potentialJson.contains(":")) {
                    cleaned = potentialJson;
                    log.info("从推理模型输出中提取到JSON，长度: {}", cleaned.length());
                }
            }
        }

        // 如果上面没有找到，使用原来的逻辑：查找第一个 { 和最后一个 }
        if (!cleaned.startsWith("{")) {
            int firstBrace = cleaned.indexOf('{');
            int lastBraceSimple = cleaned.lastIndexOf('}');

            if (firstBrace != -1 && lastBraceSimple != -1 && firstBrace < lastBraceSimple) {
                // 提取 {} 之间的内容
                cleaned = cleaned.substring(firstBrace, lastBraceSimple + 1);
            }
        }

        return cleaned.trim();
    }

    /**
     * 获取历史文件列表
     */
    @Operation(summary = "获取历史文件列表")
    @GetMapping("/history/{sessionId}")
    public Result<Map<String, Object>> getFileHistory(@PathVariable String sessionId) {
        log.info("获取历史文件列表, sessionId: {}", sessionId);

        Map<String, Object> result = new HashMap<>();
        result.put("sessionId", sessionId);
        result.put("files", new Object[]{});

        return Result.success(result);
    }

    /**
     * 下载生成的文件
     */
    @Operation(summary = "下载生成的文件")
    @GetMapping("/download/generated/{fileName}")
    public void downloadGeneratedFile(
            @PathVariable String fileName,
            HttpServletResponse response) throws IOException {

        log.info("下载生成文件: {}", fileName);

        Path filePath = Paths.get(GENERATED_DIR, fileName);

        if (!Files.exists(filePath)) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        try (FileInputStream fis = new FileInputStream(filePath.toFile())) {
            fis.transferTo(response.getOutputStream());
            response.getOutputStream().flush();
        }
    }

    /**
     * 生成询问笔录
     * 对接 workflow 前端的 /api/files/generate-interrogation 接口
     */
    @Operation(summary = "生成询问笔录")
    @PostMapping("/generate-interrogation")
    public Result<Map<String, Object>> generateInterrogation(
            @RequestBody Map<String, Object> request) {

        log.info("收到生成询问笔录请求");

        String sessionId = (String) request.get("sessionId");
        String caseApprovalContent = (String) request.get("caseApprovalContent");

        if (caseApprovalContent == null || caseApprovalContent.isEmpty()) {
            return Result.error("缺少立案审批表内容");
        }

        log.info("sessionId: {}, 立案审批表内容长度: {}", sessionId, caseApprovalContent.length());

        try {
            // 调用询问笔录生成服务
            Map<String, Object> result = interrogationGenerationService.generateInterrogationRecord(
                    caseApprovalContent, sessionId);

            log.info("询问笔录生成成功");
            return Result.success(result);

        } catch (Exception e) {
            log.error("生成询问笔录失败", e);
            return Result.error("生成询问笔录失败: " + e.getMessage());
        }
    }

    /**
     * 生成询问笔录
     * 对接 workflow 前端的 /api/files/generate-interrogation 接口
     */
    @Operation(summary = "生成询问笔录")
    @PostMapping("/Collective-Proposal")
    public Result<Map<String, Object>> generateCollectiveProposal(
            @RequestBody Map<String, Object> request) {

        log.info("收到生成集体议案请求");

        String sessionId = (String) request.get("sessionId");
        String caseApprovalContent = (String) request.get("caseApprovalContent");

        if (caseApprovalContent == null || caseApprovalContent.isEmpty()) {
            return Result.error("缺少立案审批表内容");
        }

        log.info("sessionId: {}, 立案审批表内容长度: {}", sessionId, caseApprovalContent.length());

        try {
            // 调用询问笔录生成服务
            Map<String, Object> result = interrogationGenerationService.generateInterrogationRecord(
                    caseApprovalContent, sessionId);

            log.info("询问笔录生成成功");
            return Result.success(result);

        } catch (Exception e) {
            log.error("生成询问笔录失败", e);
            return Result.error("生成询问笔录失败: " + e.getMessage());
        }
    }

}

